import * as Cesium from 'cesium';
import * as turf from '@turf/turf';

function Measure(viewer) {
    this.viewer = viewer;
    this.positions = [];
    this.polyline = null;
    this.polygon = null;
    this.labels = [];
    this.controlPoints = [];
    this.floatLabel = null;
    this.handler = null;
    this.movePush = false;
    this.tooltip = document.createElement('div');
    this.tooltip.style.zIndex = 9999;
    this.tooltip.id = 'toolTip';
    this.tooltip.style.position = 'absolute';
    this.tooltip.style.fontSize = '12px';
    this.tooltip.style.background = 'rgba(0,0,0,0.8)';
    this.tooltip.style.color = '#fff';
    this.tooltip.style.padding = '3px 5px';
    this.tooltip.style.display = 'none';

    this.lastDistance = null;
    this.allDistance = null;
    this.lastCartesian = null;
    document.body.appendChild(this.tooltip);
}
Measure.prototype.measure = function (type) {
    //默认测距离，传area测面积
    if (type == 'area') {
        this.startEdit();
    } else {
        this.startEditDistance();
    }
};

Measure.prototype.clearEdit = function () {
    this.positions = [];
    if (this.polyline) {
        this.viewer.entities.remove(this.polyline);
        this.polyline = null;
    }
    if (this.polygon) {
        this.viewer.entities.remove(this.polygon);
        this.polygon = null;
    }
    for (let ind = 0; ind < this.labels.length; ind++) {
        this.viewer.entities.remove(this.labels[ind]);
    }
    this.labels = [];
    for (let ind = 0; ind < this.controlPoints.length; ind++) {
        this.viewer.entities.remove(this.controlPoints[ind]);
    }
    this.controlPoints = [];
    if (this.floatLabel) {
        this.viewer.entities.remove(this.floatLabel);
        this.floatLabel = null;
    }
    this.floatLabel = null;
    if (this.handler) {
        this.handler.destroy();
        this.handler = null;
    }
    this.movePush = false;
    this.viewer.trackedEntity = undefined;
};

Measure.prototype.startEdit = function () {
    this.clearEdit();
    this.tooltip.style.display = 'block';

    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

    let self = this;
    //左键单击，开始绘制
    this.handler.setInputAction(
        function (evt) {
            console.log('左键单击，开始绘制');

            let cartesian = this.viewer.scene.pickPosition(evt.position);
            // let cartesian = this.getCatesian3FromPX(evt.position, self.viewer).cartesian;
            if (!cartesian) return;
            if (this.movePush) {
                this.positions.pop();
                this.movePush = false;
            }
            let point = this.createPoint(cartesian.clone());
            point.wz = this.positions.length; // 和坐标点关联
            this.controlPoints.push(point);
            this.positions.push(cartesian);
        }.bind(this),
        Cesium.ScreenSpaceEventType.LEFT_CLICK
    );

    //鼠标移动
    this.handler.setInputAction(
        function (evt) {
            this.tooltip.style.left = evt.endPosition.x + 40 + 'px';
            this.tooltip.style.top = evt.endPosition.y + 30 + 'px';
            if (this.positions.length < 1) {
                this.tooltip.innerHTML = '<p>单击开始绘制</p>';
                return;
            }
            this.tooltip.innerHTML = '<p>双击结束，右键取消上一步</p>';

            let cartesian = this.viewer.camera.pickEllipsoid(evt.endPosition, self.viewer.scene.globe.ellipsoid);
            // let cartesian = this.getCatesian3FromPX(evt.endPosition, self.viewer).cartesian;
            if (!cartesian) return;

            if (this.positions.length >= 1) {
                if (!this.movePush) {
                    this.positions.push(cartesian);
                    this.movePush = true;
                } else {
                    this.positions[this.positions.length - 1] = cartesian;
                }
                if (this.positions.length == 2) {
                    if (!Cesium.defined(this.polyline)) {
                        this.polyline = this.createPolyline();
                    }
                }
                if (this.positions.length == 3) {
                    if (!Cesium.defined(this.polygon)) {
                        this.polygon = this.createPolygon();
                        this.polygon.isFilter = true;
                        this.polygon.objId = Number(
                            new Date().getTime() + '' + Number(Math.random() * 1000).toFixed(0)
                        );
                    }
                    if (!this.floatLabel) {
                        this.floatLabel = this.createLabel(cartesian, '', {
                            style: Cesium.LabelStyle.FILL,
                            showBackground: true,
                            backgroundColor: Cesium.Color.fromCssColorString('#303336'),
                            pixelOffset: new Cesium.Cartesian2(0, -50)
                        });
                        this.floatLabel.label.heightReference = 1;
                    }
                }
                if (this.polygon) {
                    let areaCenter = this.getAreaAndCenter(this.positions);
                    let area = areaCenter.area;
                    let center = areaCenter.center;

                    let text = this.formateArea(area);
                    this.floatLabel.label.text = `平面面积：${text}`;
                    this.floatLabel.area = area;
                    if (center) this.floatLabel.position.setValue(center);
                    this.floatLabel.show = true;
                }
            }
        }.bind(this),
        Cesium.ScreenSpaceEventType.MOUSE_MOVE
    );

    //右键取消上一步
    this.handler.setInputAction(
        function (evt) {
            if (!this.polyline && !this.polygon) return;
            if (this.positions.length <= 2) return; // 默认第一个不给删除
            this.positions.splice(this.positions.length - 2, 1);
            this.viewer.entities.remove(this.controlPoints.pop()); // 移除最后一个

            if (this.positions.length == 2) {
                if (this.polygon) {
                    this.viewer.entities.remove(this.polygon);
                    this.polygon = null;
                    if (this.polyline) this.polyline.show = true;
                }
                this.floatLabel.show = false;
            }
            if (this.positions.length == 1) {
                if (this.polyline) {
                    this.viewer.entities.remove(this.polyline);
                    this.polyline = null;
                }
                this.tooltip.innerHTML = '<p>单击开始测量</p>';
                this.tooltip.style.left = evt.endPosition.x + 40 + 'px';
                this.tooltip.style.top = evt.endPosition.y + 30 + 'px';
                this.movePush = false;
                this.positions = [];
            }
            if (this.positions.length > 2) {
                let areaCenter = this.getAreaAndCenter(this.positions);
                let area = areaCenter.area;
                let center = areaCenter.center;
                let text = this.formateArea(area);
                this.floatLabel.label.text = `平面面积：${text}`;
                if (center) this.floatLabel.position.setValue(center);
                this.floatLabel.area = area;
                this.floatLabel.show = true;
            }
        }.bind(this),
        Cesium.ScreenSpaceEventType.RIGHT_CLICK
    );

    //左键双击完成绘制
    this.handler.setInputAction(
        function (evt) {
            if (!this.polygon) return;

            this.tooltip.style.display = 'none';

            this.positions.pop();
            this.viewer.entities.remove(this.controlPoints.pop()); // 移除最后一个
            this.movePush = false;

            this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
            this.viewer.trackedEntity = undefined;
            let areaCenter = this.getAreaAndCenter(this.positions);
            let area = areaCenter.area;
            let center = areaCenter.center;
            let text = this.formateArea(area);
            this.floatLabel.label.text = `平面面积：${text}`;
            this.floatLabel.area = area;
            if (center) this.floatLabel.position.setValue(center);

            if (this.handler) {
                this.handler.destroy();
                this.handler = null;
            }
        }.bind(this),
        Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    );
};

Measure.prototype.createPoint = function (position) {
    if (!position) return;

    return this.viewer.entities.add({
        position: position,
        point: {
            pixelSize: 6,
            color: Cesium.Color.RED,
            outlineWidth: 1,
            outlineColor: Cesium.Color.WHITE,
            disableDepthTestDistance: Number.POSITIVE_INFINITY
        },
        show: false
    });
};

Measure.prototype.createPolyline = function () {
    let ent = this.viewer.entities.add({
        polyline: {
            positions: new Cesium.CallbackProperty(
                function () {
                    let linePositions = this.positions.concat([this.positions[0]]);
                    return linePositions;
                }.bind(this),
                false
            ),
            material: Cesium.Color.RED,
            width: 2
        }
    });
    return ent;
};

Measure.prototype.createPolygon = function () {
    let polygon = this.viewer.entities.add({
        polygon: new Cesium.PolygonGraphics({
            hierarchy: new Cesium.CallbackProperty(
                function () {
                    return new Cesium.PolygonHierarchy(this.positions);
                }.bind(this),
                false
            ),
            material: Cesium.Color.RED.withAlpha(0.4),
            heightReference: Cesium.HeightReference.NONE,
            perPositionHeight: true
        })
    });
    return polygon;
};

Measure.prototype.getAreaAndCenter = function (positions, height) {
    if (!positions || positions.length < 1) return;
    let cartographics = [];
    let turfPoints = [];
    for (let i = 0; i < positions.length; i++) {
        let cartesian3 = positions[i];
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
        cartographics.push([
            Cesium.Math.toDegrees(cartographic.longitude),
            Cesium.Math.toDegrees(cartographic.latitude)
        ]);
        turfPoints.push(
            turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)])
        );
    }
    if (!cartographics.length) return;
    cartographics = cartographics.concat([cartographics[0]]);
    let polygon = turf.polygon([cartographics]);
    let area = turf.area(polygon);
    //获取当前范围的中心点
    let features = turf.featureCollection(turfPoints);
    let turfCenter = turf.center(features);
    let center = turfCenter.geometry.coordinates;
    let centerNum = height
        ? Cesium.Cartesian3.fromDegrees(center[0], center[1], height)
        : Cesium.Cartesian3.fromDegrees(center[0], center[1]);

    return {
        area: area,
        center: centerNum
    };
};

Measure.prototype.formateArea = function (val) {
    if (val == undefined) return;
    let dwStr = '';
    if (Number(val) > 1000000) {
        dwStr += (Number(val) / 1000000).toFixed(2) + 'km²';
    } else {
        dwStr += Number(val).toFixed(2) + 'm²';
    }
    return dwStr;
};

Measure.prototype.createLabel = function (c, text, params) {
    if (!c) return;
    return this.viewer.entities.add({
        position: c,
        label: {
            text: text || '',
            font: '14px Helvetica',
            showBackground: params ? params.showBackground : false,
            backgroundColor: params ? params.backgroundColor : Cesium.Color.WHITE,
            backgroundPadding: new Cesium.Cartesian2(10, 8),
            fillColor: params ? params.fillColor : Cesium.Color.WHITE,
            outlineColor: params ? params.outlineColor : Cesium.Color.BLACK,
            outlineWidth: 2,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            pixelOffset: params ? params.pixelOffset : new Cesium.Cartesian2(0, -20)
        }
    });
};

Measure.prototype.getCatesian3FromPX = function (px) {
    console.log(px);
    let picks = this.viewer.scene.drillPick(px);
    this.viewer.scene.render();
    let cartesian;
    let isOn3dtiles = 'no';
    for (let i = 0; i < picks.length; i++) {
        if (picks[i] && picks[i].primitive && picks[i].primitive instanceof Cesium.Cesium3DTileset) {
            //模型上拾取
            isOn3dtiles = 'yes';
            break;
        }
    }
    if (isOn3dtiles == 'yes') {
        cartesian = this.viewer.scene.pickPosition(px);
    } else {
        let ray = this.viewer.camera.getPickRay(px);
        console.log(ray);
        if (!ray) return null;
        cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
        if (this.viewer.scene.globe) {
            console.log('Globe is loaded');
        } else {
            console.log('Globe is not loaded');
        }
        console.log(cartesian);
    }
    return { cartesian: cartesian, isOn3dtiles: isOn3dtiles };
};

Measure.prototype.startEditDistance = function () {
    this.clearEdit();
    this.tooltip.style.display = 'block';

    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

    let self = this;
    //左键单击，开始绘制
    self.handler.setInputAction(function (evt) {
        let cartesian = self.viewer.scene.pickPosition(evt.position);
        if (!cartesian) return;
        if (self.movePush) {
            self.positions.pop();
            self.movePush = false;
        }
        let label;
        if (self.positions.length == 0) {
            label = self.createLabel(cartesian, '起点', {
                style: Cesium.LabelStyle.FILL,
                showBackground: true,
                backgroundColor: Cesium.Color.fromCssColorString('#303336'),
                pixelOffset: new Cesium.Cartesian2(0, -30)
            });
            self.floatLabel = self.createLabel(cartesian, '', {
                style: Cesium.LabelStyle.FILL,
                showBackground: true,
                backgroundColor: Cesium.Color.fromCssColorString('#303336'),
                pixelOffset: new Cesium.Cartesian2(0, -50)
            });
            self.floatLabel.wz = 0;
            self.floatLabel.show = false;
        } else {
            let distance = getLength(cartesian, self.lastCartesian);
            self.lastDistance = distance;
            self.allDistance += distance;
            // let text = formateLength(distance);

            label = self.createLabel(cartesian, '', {
                style: Cesium.LabelStyle.FILL,
                showBackground: true,
                backgroundColor: Cesium.Color.fromCssColorString('#303336'),
                pixelOffset: new Cesium.Cartesian2(0, -30)
            });
            label.wz = self.positions.length; // 和坐标点关联
            label.distance = distance;

            let preStr = label.isLast ? '总长：' : '';
            let curLength = formateLength(distance);
            if (label.wz > 1) {
                //第2个点往后，显示单段长度和总长度
                let allDistanceStr = formateLength(self.allDistance);
                label.label.text = preStr + allDistanceStr + '\n' + '(+' + curLength + ')';
            } else {
                label.label.text = preStr + curLength;
            }
        }
        self.labels.push(label);
        let point = self.createPoint(cartesian.clone());
        point.wz = self.positions.length; // 和坐标点关联
        self.controlPoints.push(point);
        self.positions.push(cartesian);
        self.lastCartesian = cartesian.clone();
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    //鼠标移动
    self.handler.setInputAction(function (evt) {
        let cartesian = self.viewer.camera.pickEllipsoid(evt.endPosition, self.viewer.scene.globe.ellipsoid);
        if (!cartesian) return;
        self.tooltip.style.left = evt.endPosition.x + 40 + 'px';
        self.tooltip.style.top = evt.endPosition.y + 30 + 'px';

        if (self.positions.length < 1) {
            self.tooltip.innerHTML = '<p>单击开始测量</p>';
            return;
        } else {
            self.tooltip.innerHTML = '<p>双击结束，右键取消上一步</p>';
            self.floatLabel.show = true;

            if (!self.movePush) {
                self.positions.push(cartesian);
                self.movePush = true;
            } else {
                self.positions[self.positions.length - 1] = cartesian;
            }

            if (!Cesium.defined(self.polyline)) {
                self.polyline = self.createLine(self.positions, false);
                self.polyline.objId = Number(new Date().getTime() + '' + Number(Math.random() * 1000).toFixed(0));
            }
            if (!self.lastCartesian) return;
            let distance = getLength(cartesian, self.lastCartesian);
            self.floatLabel.show = true;
            self.floatLabel.label.text = formateLength(distance);
            self.floatLabel.distance = distance;
            self.floatLabel.position.setValue(cartesian);
        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    //右键取消上一步
    self.handler.setInputAction(function (evt) {
        if (!self.polyline) return;
        if (self.positions.length <= 2) return; // 默认第一个不给删除
        self.positions.splice(self.positions.length - 2, 1);
        self.viewer.entities.remove(self.labels.pop());
        self.viewer.entities.remove(self.controlPoints.pop()); // 移除最后一个
        self.allDistance = self.allDistance - self.lastDistance;
        if (self.positions.length == 1) {
            if (self.polyline) {
                self.viewer.entities.remove(self.polyline);
                self.polyline = null;
            }
            self.movePush = false;
            self.floatLabel.show = false;
            self.positions = [];
        }
        let cartesian = self.viewer.scene.pickPosition(evt.position);
        if (!cartesian) return;
        let distance = getLength(cartesian, self.positions[self.positions.length - 2]);
        self.floatLabel.show = true;
        self.floatLabel.label.text = formateLength(distance);
        self.floatLabel.distance = distance;
        self.floatLabel.position.setValue(cartesian);

        if (!self.movePush) {
            self.lastCartesian = self.positions[self.positions.length - 1];
        } else {
            self.lastCartesian = self.positions[self.positions.length - 2];
        }
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

    //左键双击完成绘制
    self.handler.setInputAction(function (evt) {
        if (!self.polyline) return;

        self.tooltip.style.display = 'none';

        self.positions.pop();
        self.viewer.entities.remove(self.labels.pop());
        self.viewer.entities.remove(self.controlPoints.pop()); // 移除最后一个

        self.movePush = false;

        if (!self.polyline) return;
        self.floatLabel.show = false;
        self.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
        self.viewer.trackedEntity = undefined;

        // let allDistanceStr = formateLength(allDistance);
        // labels[labels.length - 1].label.text = "总长：" + allDistanceStr;

        self.labels[self.labels.length - 1].isLast = true;

        if (self.handler) {
            self.handler.destroy();
            self.handler = null;
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
};

Measure.prototype.createLine = function (positions, clampToGround) {
    if (!positions) return;
    let ent = this.viewer.entities.add({
        polyline: {
            positions: new Cesium.CallbackProperty(function () {
                return positions;
            }, false),
            show: true,
            material: Cesium.Color.RED,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            width: 2,
            clampToGround: clampToGround
        }
    });
    return ent;
};

function formateLength(val) {
    if (val == undefined) return;
    let dwStr = '';
    if (Number(val) > 1000) {
        dwStr += (Number(val) / 1000).toFixed(2) + '千米';
    } else {
        dwStr += Number(val).toFixed(2) + '米';
    }
    return dwStr;
}

function getLength(c1, c2) {
    if (!c1 || !c2) return 0;
    return Cesium.Cartesian3.distance(c1, c2) || 0;
}

export default Measure;
